package com.htsc.mrp.dao;

import com.htsc.mrp.base.BaseEntity;
import com.htsc.mrp.utils.Pagination;
import com.htsc.mrp.utils.PagingResult;
import org.apache.ibatis.session.RowBounds;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.dao.DataAccessException;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: BaseDao
 * @Description: 数据库操作基本实现类
 */
public abstract class BaseDao extends SqlSessionDaoSupport {

    protected static Logger log = Logger.getLogger(BaseDao.class);

    @Resource(name = "sqlSession")
    public SqlSessionTemplate sqlSession;

    @Override
    @Resource(name = "sqlSession")
    public void setSqlSessionTemplate(SqlSessionTemplate sqlSession) {
        super.setSqlSessionTemplate(sqlSession);
    }

    public Integer insert(String statementName, BaseEntity entity) {
        try {
            Date curTime=new Date();
            entity.setCreateTime(curTime);
            entity.setUpdateTime(curTime);
            return sqlSession.insert(statementName, entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Integer insert(String statementName, Object object) {
        try {
            return sqlSession.insert(statementName, object);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Integer insertBatch(String statementName, Object list) {
        try {
            return sqlSession.insert(statementName, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Integer update(String statementName, BaseEntity entity) {
        if (entity != null) {
            entity.setUpdateTime(new Date());
        }
        try {
            return sqlSession.update(statementName, entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 更新考虑排他
     *
     * @param statementName
     * @param entity
     * @return
     */
    public Integer updateForConcurrent(String statementName, BaseEntity entity) {
        entity.setUpdateTime(new Date());
        int updateCount = sqlSession.update(statementName, entity);
        if (updateCount == 0) {
            throw new RuntimeException("数据库并发更新异常");
        } else {
            return updateCount;
        }
    }

    public Integer update(String statementName, Object obj) {
        try {
            return sqlSession.update(statementName, obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public int delete(String statementName, BaseEntity entity) {
        try {
            return sqlSession.delete(statementName, entity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public int delete(String statementName, Object param) {
        try {
            return sqlSession.delete(statementName, param);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除考虑并发
     *
     * @param statementName
     * @param entity
     * @return
     */
    public int deleteForConcurrent(String statementName, BaseEntity entity) {
        int updateCount = sqlSession.delete(statementName, entity);
        if (updateCount == 0) {
            throw new RuntimeException("数据库并删除新异常");
        } else {
            return updateCount;
        }
    }

    public <T> PagingResult<T> selectPagination(String statementName, String countStatementName, Pagination pagination)
            throws RuntimeException {
        try {
            // 默认为第一页
            int page = pagination.getPage();
            // 默认每页15个
            int size = pagination.getSize();

            RowBounds rowBounds = new RowBounds((page - 1) * size, size);

            Map<Object, Object> param = pagination.getParams();
            if (param != null) {
                param.put("orderColumn", pagination.getOrderColumn());
                param.put("orderTurn", pagination.getOrderTurn());
            } else {
                param = new HashMap<Object, Object>();
                param.put("orderColumn", pagination.getOrderColumn());
                param.put("orderTurn", pagination.getOrderTurn());
            }

            List<T> resultList = sqlSession.selectList(statementName, param, rowBounds);
            int totalSize = count(countStatementName, pagination.getParams());

            PagingResult<T> pagingResult = new PagingResult<T>();
            pagingResult.setCurrentPage(page);
            pagingResult.setTotalSize(totalSize);
            pagingResult.setPageSize(size);
            pagingResult.setDataList(resultList);
            return pagingResult;
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public <T> T selectOne(String statementName, Object obj) throws RuntimeException {
        try {
            return sqlSession.selectOne(statementName, obj);
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public int count(String statementName, Object param) throws RuntimeException {
        try {
            return sqlSession.selectOne(statementName, param);
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public <T> List<T> select(String statementName) throws RuntimeException {
        try {
            return sqlSession.selectList(statementName);
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public <T> List<T> select(String statementName, Object obj) throws RuntimeException {
        try {
            return sqlSession.selectList(statementName, obj);
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void executeSP(String statementName, Object param) {
        try {
            sqlSession.selectOne(statementName, param);
        } catch (DataAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
